<html>
<head><meta charset="utf-8"><title>Calls in MIR · t-compiler/help · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/index.html">t-compiler/help</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Calls.20in.20MIR.html">Calls in MIR</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="181812247"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Calls%20in%20MIR/near/181812247" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Edd Barrett <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Calls.20in.20MIR.html#181812247">(Nov 25 2019 at 11:26)</a>:</h4>
<p>Hi everyone,</p>
<p>I have some questions about calls in MIR which I've been unable to tease out from the compiler source code.</p>
<p>I'm looking at a call site in the optimised MIR of a program. The call  target is a <code>TyKind::FnDef</code>, which is expressed as a <code>DefId</code> and a <code>SubstsRef</code>. Using <code>println</code> debugging, I've determined that the <code>DefId</code> in question is never code-genned. That's likely because the callee in question is a trait function with no default implementation. The function does have a concrete implementation elsewhere (in the same crate) though.</p>
<p>Nonetheless I was quite surprised that a dynamic call to a trait function is a <code>TyKind::FnDef</code>. I thought that these kinds of calls would be distinguished from normal static calls via another variant (perhaps <code>TyKind::FnPtr</code>?).</p>
<p>So are calls to trait functions indistinguishable from normal static calls at the MIR level? It occurs to me that the trait  in question has only one implementation. I wonder if that has something to do with it? Perhaps the compiler "promotes" the dynamic call to a static call?</p>
<p>Next, supposing there's a way to know if any given call is to a trait function, is there a way (inside the compiler) to enumerate the potential callees?</p>
<p>Context: I'm working on something which requires the ability to be able to distinguish a function with no MIR from a function which is a "stub" (no default impl)  in a trait.</p>
<p>Thanks!</p>



<a name="181818129"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Calls%20in%20MIR/near/181818129" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Matthew Jasper <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Calls.20in.20MIR.html#181818129">(Nov 25 2019 at 12:38)</a>:</h4>
<p>Virtual calls (<code>&lt;dyn Trait as Trait&gt;::method</code>) are turned into a  reading a function pointer from the vtable and then calling it.</p>



<a name="181818299"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Calls%20in%20MIR/near/181818299" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Matthew Jasper <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Calls.20in.20MIR.html#181818299">(Nov 25 2019 at 12:40)</a>:</h4>
<p>Other trait methods are codegened with the DefId from the impl, while in MIR the may use the DefId from the trait item.</p>



<a name="181818466"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Calls%20in%20MIR/near/181818466" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Matthew Jasper <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Calls.20in.20MIR.html#181818466">(Nov 25 2019 at 12:43)</a>:</h4>
<p>What do you mean by a function with no mir? One where it isn't available? Or one where it never existed on the first place?</p>



<a name="181820981"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Calls%20in%20MIR/near/181820981" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Edd Barrett <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Calls.20in.20MIR.html#181820981">(Nov 25 2019 at 13:17)</a>:</h4>
<p>Hi Matthew,</p>
<blockquote>
<p>Other trait methods are codegened with the DefId from the impl, while in MIR the may use the DefId from the trait item.</p>
</blockquote>
<p>Right, so I suppose I'm seeing the latter. At least, I see no <code>TyKind::FnPtr</code> in the target.</p>
<p>Is there a way to identify if a call is to a trait item, and if so, enumerate its impls? That'd be very useful.</p>
<blockquote>
<p>What do you mean by a function with no mir?</p>
</blockquote>
<p>In my case, it's functions where <code>tcx.is_mir_available()</code> returns true after all passes have run, and right before the codegen.</p>
<p>Thanks</p>



<a name="181822195"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Calls%20in%20MIR/near/181822195" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Edd Barrett <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Calls.20in.20MIR.html#181822195">(Nov 25 2019 at 13:32)</a>:</h4>
<blockquote>
<p>while in MIR the may use the DefId from the trait item.</p>
</blockquote>
<p>And I guess, is there a way to resolve the call to a concrete function?</p>



<a name="181824882"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Calls%20in%20MIR/near/181824882" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Matthew Jasper <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Calls.20in.20MIR.html#181824882">(Nov 25 2019 at 14:09)</a>:</h4>
<blockquote>
<blockquote>
<p>while in MIR the may use the DefId from the trait item.</p>
</blockquote>
<p>And I guess, is there a way to resolve the call to a concrete function?</p>
</blockquote>
<p>ty::Instance::resolve</p>



<a name="181825031"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Calls%20in%20MIR/near/181825031" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Matthew Jasper <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Calls.20in.20MIR.html#181825031">(Nov 25 2019 at 14:10)</a>:</h4>
<p>Well, that requires running during monomorphization.</p>



<a name="181826422"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Calls%20in%20MIR/near/181826422" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Edd Barrett <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Calls.20in.20MIR.html#181826422">(Nov 25 2019 at 14:26)</a>:</h4>
<p>I've already experimented with <code>Instance::resolve()</code>, but figured it wasn't right due to:</p>
<div class="codehilite"><pre><span></span>error: internal compiler error: src/librustc/traits/codegen/mod.rs:53: Encountered error `Unimplemented`
selecting `Binder(&lt;F as std::ops::Fn&lt;(f64,)&gt;&gt;)` during codegen
</pre></div>


<p>I also tried <code>tcx.subst_and_normalize_erasing_regions()</code>. Whilst this didn't crash, it didn't resolve the DefId in <code>question</code> either.</p>
<blockquote>
<p>Well, that requires running during monomorphization.</p>
</blockquote>
<p>Can you tell me more about this?</p>



<a name="181831018"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Calls%20in%20MIR/near/181831018" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Edd Barrett <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Calls.20in.20MIR.html#181831018">(Nov 25 2019 at 15:11)</a>:</h4>
<p>By the way, I just realised that I am actually running my code <em>after</em> codegen, not before (in case that changes anything).</p>
<p>I run after:</p>
<div class="codehilite"><pre><span></span>codegen_backend.codegen_crate(...)
</pre></div>



<a name="181839495"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Calls%20in%20MIR/near/181839495" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Edd Barrett <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Calls.20in.20MIR.html#181839495">(Nov 25 2019 at 16:39)</a>:</h4>
<blockquote>
<p>Well, that requires running during monomorphization.</p>
</blockquote>
<p>I guess this relates to:</p>
<div class="codehilite"><pre><span></span>error: internal compiler error: src/librustc/traits/codegen/mod.rs:127: Encountered errors `[FulfillmentE
rror(Obligation(predicate=Binder(TraitPredicate(&lt;R as std::marker::Sized&gt;)), depth=1),Unimplemented)]` re
solving bounds after type-checking
</pre></div>


<p>i.e. I'm <code>resolve()</code>ing too late :(</p>



<a name="181857839"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Calls%20in%20MIR/near/181857839" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Matthew Jasper <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Calls.20in.20MIR.html#181857839">(Nov 25 2019 at 20:06)</a>:</h4>
<blockquote>
<p>Hi Matthew,</p>
<blockquote>
<p>Other trait methods are codegened with the DefId from the impl, while in MIR the may use the DefId from the trait item.</p>
</blockquote>
<p>Right, so I suppose I'm seeing the latter. At least, I see no <code>TyKind::FnPtr</code> in the target.</p>
<p>Is there a way to identify if a call is to a trait item, and if so, enumerate its impls? That'd be very useful.</p>
<blockquote>
<p>What do you mean by a function with no mir?</p>
</blockquote>
<p>In my case, it's functions where <code>tcx.is_mir_available()</code> returns true after all passes have run, and right before the codegen.</p>
<p>Thanks</p>
</blockquote>
<p>You can list all impls with <code>tcx.trait_of_item</code> and <code>tcx.all_impls</code>. Then <code>tcx.associated_items</code> will give an iterator over the associated items for each impl. Which can then be filters by ident and kind. (See <a href="https://github.com/rust-lang/rust/blob/781866f3a95da0e4a35151cc24523f186ce19c79/src/librustc/traits/specialize/specialization_graph.rs#L440" target="_blank" title="https://github.com/rust-lang/rust/blob/781866f3a95da0e4a35151cc24523f186ce19c79/src/librustc/traits/specialize/specialization_graph.rs#L440">https://github.com/rust-lang/rust/blob/781866f3a95da0e4a35151cc24523f186ce19c79/src/librustc/traits/specialize/specialization_graph.rs#L440</a>)</p>



<a name="181913593"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Calls%20in%20MIR/near/181913593" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Edd Barrett <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Calls.20in.20MIR.html#181913593">(Nov 26 2019 at 11:53)</a>:</h4>
<p>Thanks Matthew. I'll have a play around and see if this works for me.</p>
<p>Thanks so much for the pointers.</p>



<a name="181938940"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Calls%20in%20MIR/near/181938940" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Edd Barrett <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Calls.20in.20MIR.html#181938940">(Nov 26 2019 at 16:32)</a>:</h4>
<p>Hi Matthew,</p>
<p>I was able to enumerate the associated items of the trait, so thanks for this :)</p>
<p>Just to be clear: there's no way of knowing which of the candidates will actually be called without "being the codegen"?</p>



<a name="181962838"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Calls%20in%20MIR/near/181962838" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Matthew Jasper <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Calls.20in.20MIR.html#181962838">(Nov 26 2019 at 20:54)</a>:</h4>
<p>It's actually <code>rustc_mir::monomorphize::collector</code> that does this. You could probably copy the implementation there if the <code>collect_and_partition_mono_items</code> query isn't providing enough information.</p>



<a name="182013610"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Calls%20in%20MIR/near/182013610" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Edd Barrett <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Calls.20in.20MIR.html#182013610">(Nov 27 2019 at 12:26)</a>:</h4>
<blockquote>
<p>It's actually rustc_mir::monomorphize::collector that does this.</p>
</blockquote>
<p>The function responsible for resolving the call sites in the collector is <code>visit_fn_use()</code>. I changed it to cache the results of resolutions into a hashmap keyed by instance (in the <code>tcx</code>. yeah, I know, gross). That way I can access them later.</p>
<p>So the function now looks like this:</p>
<div class="codehilite"><pre><span></span>fn visit_fn_use&lt;&#39;tcx&gt;(
    tcx: TyCtxt&lt;&#39;tcx&gt;,
    ty: Ty&lt;&#39;tcx&gt;,
    is_direct_call: bool,
    output: &amp;mut Vec&lt;MonoItem&lt;&#39;tcx&gt;&gt;,
) {
    if let ty::FnDef(def_id, substs) = ty.kind {
        let resolver = if is_direct_call {
            ty::Instance::resolve
        } else {
            ty::Instance::resolve_for_fn_ptr
        };
        let instance = resolver(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap();

        let mut resolutions = tcx.call_resolution_map.borrow_mut();
        if resolutions.is_none() {
            *resolutions = Some(FxHashMap::default());
        }
        let pre_inst = Instance::new(def_id, substs);

        if tcx.def_path_str(def_id).contains(&quot;stop_tracing&quot;) {
            dbg!(&amp;pre_inst);
            dbg!(instance);
        }

        resolutions.as_mut().unwrap().insert(pre_inst, instance);

        visit_instance_use(tcx, instance, is_direct_call, output);
    }
}
</pre></div>


<p>And as you can see, I have some <code>dbg!</code> in there so I can see how my problem call-site is being resolved.</p>
<div class="codehilite"><pre><span></span>[src/librustc_mir/monomorphize/collector.rs:738] &amp;pre_inst = Instance {
    def: Item(
        DefId(0:156 ~ yktrace[72ea]::ThreadTracerImpl[0]::stop_tracing[0]),
    ),
    substs: [
        dyn ThreadTracerImpl,
    ],
}
[src/librustc_mir/monomorphize/collector.rs:739] instance = Instance {
    def: Virtual(
        DefId(0:156 ~ yktrace[72ea]::ThreadTracerImpl[0]::stop_tracing[0]),
        0,
    ),
    substs: [
        dyn ThreadTracerImpl,
    ],
}
</pre></div>


<p>Seems that the call remains unresolved? I was expecting <code>substs</code> to be empty after resolution. But if that were always the case, <code>resolve()</code> would return only a <code>DefId</code>. Seems I'm missing something...</p>
<p>I think this has something to do with <code>codegen_call_terminator()</code> in <code>src/librustc_codegen_ssa/mir/block.rs</code> where there appears to a second layer of resolution?</p>



<a name="182014343"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Calls%20in%20MIR/near/182014343" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Matthew Jasper <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Calls.20in.20MIR.html#182014343">(Nov 27 2019 at 12:38)</a>:</h4>
<p>Oh, it's an actual virtual call. The concrete method gets  recorded through a path like coerce to trait object ("unsize coercion") -&gt; vtable -&gt; method.</p>



<a name="182018215"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Calls%20in%20MIR/near/182018215" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Edd Barrett <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Calls.20in.20MIR.html#182018215">(Nov 27 2019 at 13:25)</a>:</h4>
<blockquote>
<p>Oh, it's an actual virtual call. The concrete method gets recorded through a path like coerce to trait object ("unsize coercion") -&gt; vtable -&gt; method.</p>
</blockquote>
<p>So the target is only decided at runtime, right?</p>



<a name="182019800"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Calls%20in%20MIR/near/182019800" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Matthew Jasper <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Calls.20in.20MIR.html#182019800">(Nov 27 2019 at 13:45)</a>:</h4>
<p>Yes</p>



<a name="182038584"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Calls%20in%20MIR/near/182038584" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Edd Barrett <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Calls.20in.20MIR.html#182038584">(Nov 27 2019 at 17:07)</a>:</h4>
<p>Great!</p>
<p>Thanks for your patience with this. I have much to learn :)</p>



<a name="182350814"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/182449-t-compiler/help/topic/Calls%20in%20MIR/near/182350814" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> bjorn3 <a href="https://rust-lang.github.io/zulip_archive/stream/182449-t-compiler/help/topic/Calls.20in.20MIR.html#182350814">(Dec 02 2019 at 14:37)</a>:</h4>
<p>Edit: didn't read your comment completely.</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>